import Taro, { useDidHide, useDidShow, useUnload } from '@tarojs/taro'
import { createGlobalStore } from 'hox'
import { useCallback, useRef, useState } from 'react'

// 尽量通过api监听网络状态改变，如无法监听结果，则使用请求结果判断来兜底
export const [useNetworkStore, getNetworkStore] = createGlobalStore(() => {
    const [networkAvailable, setNetworkAvailable] = useState(true)
    const isIOSRef = useRef(false)
    const [isTimeout, setIsTimeout] = useState(false)
    const reCheckNetwork = useCallback(() => {
        switch (process.env.TARO_ENV) {
            case 'h5':
                window.location.reload()
                break
            default:
                // ios 在某些平台会固定返回 unknown，这里统一当做有网处理，页面会重渲染，如果无网会触发请求失败的逻辑
                Taro.getNetworkType({
                    success: function (res) {
                        const { networkType } = res
                        setNetworkAvailable(!['none', 'notreachable'].includes(networkType.toLowerCase()))
                    },
                })
                break
        }
    }, [])

    // 断网4s后显示断网页面，防抖
    const offlineTimeoutRef = useRef<NodeJS.Timeout>()
    const onOnline = useCallback(() => {
        if (offlineTimeoutRef.current) {
            clearTimeout(offlineTimeoutRef.current)
            offlineTimeoutRef.current = undefined
        }
    }, [])
    const onOffline = useCallback(() => {
        if (offlineTimeoutRef.current) return
        offlineTimeoutRef.current = setTimeout(() => setNetworkAvailable(false), 4000)
    }, [])

    // 超时控制，10s内无法再次设置为超时状态 （请求超时为10s, 但是弱网下，接受到淘宝超时请求的时间可能已经超过了10s）
    const requestTimeoutRef = useRef<NodeJS.Timeout>()
    const clearRequestTimeout = () => requestTimeoutRef.current = undefined
    const requestTimeout = useCallback(() => {
        if (requestTimeoutRef.current) return
        setIsTimeout(true)
        requestTimeoutRef.current = setTimeout(clearRequestTimeout, 10 * 1000)
    }, [])
    const resetRequestTimeout = useCallback(() => setIsTimeout(false), [])
    useUnload(() => {
        if (requestTimeoutRef.current) clearTimeout(requestTimeoutRef.current)
    })

    useDidShow(() => {
        Taro.getSystemInfo().then(res => {
            const platform = res.platform.toLowerCase()
            isIOSRef.current = ['iphone', 'ios'].includes(platform)
            // 兼容性太差了
            switch (process.env.TARO_ENV) {
                case 'h5':
                    window.addEventListener('offline', onOffline)
                    window.addEventListener('online', onOnline)
                    break
                case 'alipay':
                    if (isIOSRef.current) {
                        // ios 无法监听网络状态，使用请求返回值判断
                    } else {
                        Taro.onNetworkStatusChange((res) => res.isConnected ? onOnline() : onOffline())
                    }
                    break
                default:
                    Taro.onNetworkStatusChange((res) => res.isConnected ? onOnline() : onOffline())
                    break
            }
        })
    })
    useDidHide(() => {
        switch (process.env.TARO_ENV) {
            case 'h5':
                window.removeEventListener('offline', onOffline)
                window.removeEventListener('online', onOnline)
                break
            case 'alipay':
                if (isIOSRef.current) {
                    // ios 无法监听网络状态，使用请求返回值判断
                } else {
                    Taro.offNetworkStatusChange()
                }
                break
            default:
                Taro.offNetworkStatusChange()
                break
        }
        onOnline()
        resetRequestTimeout()
    })
    const pageDidShow = useCallback(() => {
        resetRequestTimeout()
        if (!networkAvailable) reCheckNetwork()
    }, [networkAvailable])

    const pageDidHide = useCallback(() => {
        resetRequestTimeout()
    }, [])

    return {
        pageDidShow, pageDidHide,
        networkAvailable,
        setUnAvailable: () => setNetworkAvailable(false),
        reCheckNetwork,
        requestWeak: () => setTimeout(() => Taro.showToast({ title: '网络环境较差，请耐心等待！', icon: 'none', duration: 3000 }), 6000),
        requestTimeout,
        isTimeout,
        resetRequestTimeout,
    }
})